/*
    This file is part of SQLiteGTK, written by Aly Hirani

    SQLiteGTK is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    SQLiteGTK is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with SQLiteGTK.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "include.h"

#ifdef ENABLE_SOURCE_VIEW
#include "main_window_notebook.h"
#include "main_window_notebook_source_view.h"
#include "util.h"

gboolean
main_window_editor_tabs_close(GtkNotebook *notebook, GList* tabs)
{
	GList *temp = tabs;

	g_assert(tabs != NULL);

	while(temp != NULL)
	{
		gtk_notebook_remove_page(notebook, gtk_notebook_page_num(notebook, GTK_WIDGET(temp->data)));
		temp = temp->next;
	}

	return TRUE;
}

/* Collectively gives the ability to save multiple tabs */
gboolean
main_window_notebook_editor_save(gpointer user_data, gint page_num)
{
	/*
	g_assert(user_data != NULL);
	g_assert(page_nums != NULL);
	
	MainWindowControls* controls = main_window_notebook_get_nth_page_controls(user_data, page_num, EMWC_SOURCE_BUFFER);
	
	if(controls->controls.source_buffer != NULL)
	{
		if(gtk_text_buffer_get_modified(GTK_TEXT_BUFFER(controls->controls.source_buffer)))
		{
			if(show_message_dialog(controls_state->main_window, GTK_DIALOG_MODAL, GTK_MESSAGE_QUESTION,
				GTK_BUTTONS_YES_NO, GTK_RESPONSE_YES, "%s has been modified. Do you wish to save the changes?", 
				get_notebook_page_label(controls_state->notebook_page_label))==GTK_RESPONSE_YES)
			{
				gchar *file_path = get_buffer_file_path(controls_state->source_buffer);
				if(!file_path)
				{
					GtkWindow *window = GTK_WINDOW(gtk_builder_get_object(struct_data->builder, "main_window"));
					g_assert(window != NULL);
					
					file_path = show_save_file_dialog(window, "Save", "SQL Files", text / * ,NULL);
					
					if(!file_path)
						return;
					
					set_buffer_file_path(controls_state->source_buffer, file_path);
					
					gchar *base_name = g_path_get_basename(file_path);
					g_assert(base_name != NULL);
					
					change_notebook_page_label(controls_state->notebook_page_label, base_name);
					
					g_free(base_name);
				}
				
				if(gtk_source_buffer_save_file(controls_state->source_buffer))
					gtk_text_buffer_set_modified(GTK_TEXT_BUFFER(controls_state->source_buffer), FALSE);
				else
					show_message_dialog(controls_state->main_window, GTK_DIALOG_MODAL, 
						GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, GTK_RESPONSE_OK, "An error occurred while trying to save the file.");
			}
		}
	}
	
	g_free(controls_state);
	*/
	return TRUE;
}

void
main_window_notebook_editor_close(gpointer user_data, gint page_num)
{
	/*
	g_assert(user_data != NULL);
	g_assert(page_num >= 0);
	
	if(main_window_editor_tab_save(user_data, page_num))
	{
		GtkBuilder *builder = GTK_BUILDER(user_data);
		g_assert(builder != NULL);
		
		GtkNotebook *notebook = GTK_NOTEBOOK(gtk_builder_get_object(builder, "editor_notebook"));
		g_assert(notebook != NULL);
		
		gtk_notebook_remove_page(notebook, page_num);
	}
	*/
}

void
main_window_editor_buffer_modified_changed_cb(GtkTextBuffer *buffer, gpointer user_data)
{
	/*
	g_assert(user_data != NULL);
	g_assert(buffer != NULL);
	
	GtkSourceView *source_view = GTK_SOURCE_VIEW(user_data);
	g_assert(source_view != NULL);
		
	GtkWidget *box = gtk_widget_get_parent(gtk_widget_get_parent(GTK_WIDGET(source_view)));
	g_assert(box != NULL);
	
	GtkNotebook *notebook = GTK_NOTEBOOK(gtk_widget_get_parent(box));
	g_assert(notebook != NULL);
	
	GtkBox *header_box = GTK_BOX(gtk_notebook_get_tab_label(notebook, box));
	g_assert(header_box != NULL);
	
	GList *children = gtk_container_get_children(GTK_CONTAINER(header_box));
	g_assert(children != NULL);
	
	GtkLabel *modified_label = g_list_nth_data(children, 1);
	g_assert(modified_label);
	
	g_list_free(children);
	
	gtk_label_set_text(modified_label, (gtk_text_buffer_get_modified(buffer) ? " *" : " "));
	*/
}

gint
main_window_notebook_editor_create(GtkBuilder *builder, const gchar *file_path, gboolean focus)
{
	/*
	g_assert(builder != NULL);
	
	GtkNotebook *notebook = GTK_NOTEBOOK(gtk_builder_get_object(builder, "editor_notebook"));
	g_assert(notebook != NULL);
	
	GtkWidget *source_scroll_window = gtk_scrolled_window_new(NULL, NULL);
	g_assert(source_scroll_window != NULL);
	
	GtkWidget *tree_scroll_window = gtk_scrolled_window_new(NULL, NULL);
	g_assert(tree_scroll_window != NULL);
	
	GtkSourceView *source_view = create_gtk_source_view(file_path);
	g_assert(source_view != NULL);
	
	GtkTextBuffer *text_buffer = GTK_TEXT_BUFFER(gtk_text_view_get_buffer(GTK_TEXT_VIEW(source_view)));
	g_assert(text_buffer != NULL);
	
	// g_signal_connect(text_buffer, "modified-changed", G_CALLBACK(source_view_on_modified_change), source_view);
	
	GtkWidget *tree_view = gtk_tree_view_new();
	g_assert(tree_view != NULL);
	
	GtkWidget *result_label = gtk_label_new(NULL);
	g_assert(result_label != NULL);
	
	GtkBox *tree_vbox = GTK_BOX(gtk_vbox_new(FALSE, 0));
	g_assert(tree_vbox != NULL);
	
	GtkPaned *paned_box = GTK_PANED(gtk_vpaned_new());
	g_assert(paned_box != NULL);
	
	GtkButton *close_button = GTK_BUTTON(gtk_button_new());
	g_assert(close_button != NULL);
	
	GtkWidget *stock_close_button = gtk_image_new_from_stock(GTK_STOCK_CLOSE, GTK_ICON_SIZE_MENU);
	g_assert(stock_close_button != NULL);
	
	gtk_button_set_image(close_button, stock_close_button);
	// g_signal_connect(close_button, "clicked", G_CALLBACK(main_window_tree_view_close_button_on_clicked), builder);
	gtk_button_set_relief(close_button, GTK_RELIEF_NONE);
	
	GtkBox *hbox_tree_view = GTK_BOX(gtk_hbox_new(FALSE, 0));
	g_assert(hbox_tree_view != NULL);
	
	gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(source_scroll_window), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
	gtk_container_add(GTK_CONTAINER(source_scroll_window), GTK_WIDGET(source_view));
	
	gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(tree_scroll_window), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
	gtk_container_add(GTK_CONTAINER(tree_scroll_window), tree_view);
	
	gtk_box_pack_end(hbox_tree_view, GTK_WIDGET(close_button), FALSE, FALSE, 0);
	gtk_box_pack_start(GTK_BOX(tree_vbox), GTK_WIDGET(hbox_tree_view), FALSE, FALSE, 0);
	gtk_box_pack_start(GTK_BOX(tree_vbox), tree_scroll_window, TRUE, TRUE, 0);
	gtk_box_pack_start(GTK_BOX(tree_vbox), result_label, FALSE, FALSE, 0);
	
	gtk_paned_add1(paned_box, GTK_WIDGET(source_scroll_window));
	gtk_paned_add2(paned_box, GTK_WIDGET(tree_vbox));
	
	gchar *caption;
	if(file_path)
	{
		caption = g_path_get_basename(file_path);
	}
	else
	{
		GObject *window = gtk_builder_get_object(builder, "main_window");
		guint *total_notebook_tabs = g_object_get_data(window, "total_notebook_tabs");
		if(!total_notebook_tabs)
		{
			total_notebook_tabs = g_malloc(sizeof(guint));
			*total_notebook_tabs = 0;
			g_object_set_data_full(window, "total_notebook_tabs", total_notebook_tabs, g_free);
		}
		caption = g_strdup_printf("Unsaved SQL %u", ++(*total_notebook_tabs));
	}
	
//	GtkWidget *header_box = main_window_notebook_create_tab_header(caption, G_CALLBACK(main_window_notebook_tab_close_on_clicked), builder);
	GtkWidget *header_box = main_window_notebook_create_tab_header(caption, NULL, builder);
	g_assert(header_box != NULL);
	
	g_object_set_data(G_OBJECT(header_box), "notebook_page", paned_box);
	
	gint result = gtk_notebook_append_page(notebook, GTK_WIDGET(paned_box), header_box);
	g_assert(result != -1);
	
	gtk_widget_show(GTK_WIDGET(paned_box));
	gtk_widget_show_all(GTK_WIDGET(source_scroll_window));
	
	if(focus)
	{
		gtk_notebook_set_current_page(notebook, result);
	}
	
	return result;
	*/
	
	return -1;
}

void
destroy_source_lang()
{
	if(source_lang)
		g_object_unref(source_lang);
	
	g_assert(source_lang_manager != NULL);
	g_object_unref(source_lang_manager);
}

void
destroy_source_style()
{
	if(source_style_scheme)
		g_object_unref(source_style_scheme);
	
	g_assert(source_style_scheme_manager != NULL);
	g_object_unref(source_style_scheme_manager);
}

gboolean
init_main_window_notebook_source_view()
{
	gchar *source_lang_file_name, *source_lang_mime_type, *source_style_id;
	GError *regex_error;

	source_lang_file_name = prefs_manager_get_string(prefs_manager, "source-lang", "file-name", NULL);
	source_lang_mime_type = prefs_manager_get_string(prefs_manager, "source-lang", "mime-type", "text/x-sql");
	
	init_source_lang(source_lang_file_name, source_lang_mime_type);
	
	g_free(source_lang_file_name);
	g_free(source_lang_mime_type);
		
	source_style_id = prefs_manager_get_string(prefs_manager, "source-style", "id", NULL);
	
	init_source_style(source_style_id);
	
	g_free(source_style_id);
		
	selection_clipboard = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD);
	
	regex_error = NULL;
	hint_regex = g_regex_new("(CREATE|ALTER|DROP|ROLLBACK)", G_REGEX_CASELESS | G_REGEX_OPTIMIZE, 0, &regex_error);
	if(regex_error)
	{
		log_warning("Unable to compile hint regex. Refresh hinting will not be available. Error message: %s", regex_error->message);
		g_error_free(regex_error);
	}

	return TRUE;
}

gboolean
uninit_main_window_notebook_source_view()
{
	destroy_source_style();
	destroy_source_lang();

	if(hint_regex)
	{
		g_regex_unref(hint_regex);
		hint_regex = NULL;
	}

	return TRUE;
}

gboolean
source_buffer_save_file(GtkSourceBuffer *source_buffer)
{
	/*
	g_assert(source_buffer != NULL);
	
	GError *err = NULL;
	GIOChannel *io = NULL;
	gboolean result = TRUE;
	
	GtkTextBuffer *text_buffer = GTK_TEXT_BUFFER(source_buffer);
	g_assert(text_buffer != NULL);
	
	gchar *file_path = get_buffer_file_path(source_buffer);
	g_assert(file_path != NULL);
	
	io = g_io_channel_new_file(file_path, "w", &err);
	if(!io)
	{
		log_error("Unable to open file: %s\n", file_path);
		result = FALSE;
		goto cleanup;
	}
	
	if (g_io_channel_set_encoding (io, "utf-8", &err) != G_IO_STATUS_NORMAL)
	{
		log_error("Unable to set UTF-8 encoding. File: %s", file_path);
		result = FALSE;
		goto cleanup;
	}
	
	GtkTextIter start, end;
	gtk_text_buffer_get_bounds(text_buffer, &start, &end);
	
	gchar *data = gtk_text_buffer_get_text(text_buffer, &start, &end, FALSE);
	
	gsize bytes;
	
	if(g_io_channel_write_chars(io, data, -1, &bytes, &err) != G_IO_STATUS_NORMAL)
	{
		log_error("Unable to write file: %s\n", file_path);
		result = FALSE;
		goto cleanup;
	}
	
cleanup:
	if(err)
		g_error_free(err);
	
	if(data)
		g_free(data);
	
	if(io)
	{
		g_io_channel_shutdown(io, TRUE, &err);
		g_io_channel_unref(io);
	}
	
	return result;
	*/
	
	return FALSE;
}

gboolean
source_buffer_open_file(GtkSourceBuffer *source_buffer, const gchar *filename)
{
	/*
	g_assert(source_buffer != NULL);
	g_assert(filename != NULL);

	GError *err = NULL;	
	gchar *buffer = NULL;
	GIOChannel *io = NULL;
	gboolean reading = TRUE;
	GtkTextIter iter;
	
	GtkTextBuffer *text_buffer = GTK_TEXT_BUFFER(source_buffer);
	g_assert(text_buffer != NULL);
	
	io = g_io_channel_new_file (filename, "r", &err);
	
	if (!io)
	{
		log_error("%s %s\n", (err)->message, filename);
		g_error_free(err);
		return FALSE;
	}
	
	if (g_io_channel_set_encoding (io, "utf-8", &err) != G_IO_STATUS_NORMAL)
	{
		g_print("err: Failed to set encoding:\n%s\n%s", filename, (err)->message);
		g_error_free(err);
		return FALSE;
	}
	
	gtk_source_buffer_begin_not_undoable_action (source_buffer);
	
	buffer = g_malloc (4096);
	while (reading)
	{
		gsize bytes_read;
		GIOStatus status;
		
		status = g_io_channel_read_chars (io, buffer, 4096, &bytes_read, &err);
		switch (status)
		{
		case G_IO_STATUS_EOF:
			reading = FALSE;
			break;
		case G_IO_STATUS_NORMAL:
			if (bytes_read == 0)
				continue;
			gtk_text_buffer_get_end_iter (text_buffer, &iter);
			gtk_text_buffer_insert (text_buffer,&iter,buffer,bytes_read);
			break;
		case G_IO_STATUS_AGAIN:
			continue;
		case G_IO_STATUS_ERROR: // fall through
		default:
			g_print("err (%s): %s", filename, (err)->message);
			// because of error in input we clear already loaded text
			gtk_text_buffer_set_text (text_buffer, "", 0);
			reading = FALSE;
			break;
		}
	}
	g_free (buffer);
	
	gtk_source_buffer_end_not_undoable_action (source_buffer);
	g_io_channel_unref (io);
	
	if (err)
	{
		g_error_free (err);
		return FALSE;
	}
	
	gtk_text_buffer_set_modified (text_buffer, FALSE);
	
	// move cursor to the beginning
	gtk_text_buffer_get_start_iter (text_buffer, &iter);
	gtk_text_buffer_place_cursor (text_buffer, &iter);
	
	set_buffer_file_path_dup(source_buffer, filename);
	
	return TRUE;
	*/
	
	return FALSE;
}

GtkSourceView
*create_gtk_source_view(const gchar *filename)
{
	/*
	GtkSourceView *view = NULL;
	GtkSourceBuffer *buf = NULL;
	PangoFontDescription *font_desc = NULL;
	
	buf = gtk_source_buffer_new(NULL);
	
	if(source_lang != NULL)
	{
		gtk_source_buffer_set_language(buf, source_lang);
		gtk_source_buffer_set_highlight_syntax(buf, TRUE);
	}
	
	if(source_style_scheme != NULL)
	{
		gtk_source_buffer_set_style_scheme(buf, source_style_scheme);
	}
	
	if(filename != NULL)
	{
		gtk_source_buffer_open_file(buf, filename);
	}
	
	view = GTK_SOURCE_VIEW(gtk_source_view_new_with_buffer(buf));
	
	g_object_set(G_OBJECT(buf), "highlight-matching-brackets", prefs_manager_get_bool(prefs_manager, 
		"source-buffer", "highlight-matching-brackets", TRUE), "highlight-syntax", 
		prefs_manager_get_bool(prefs_manager, "source-buffer", "highlight-syntax", TRUE),
		"max-undo-levels", prefs_manager_get_int(prefs_manager, "source-buffer", "max-undo-levels", 25), NULL);
	
	g_object_set (G_OBJECT (view), "auto-indent", prefs_manager_get_bool(prefs_manager, "source-view", "auto-indent", TRUE),
		"draw-spaces", prefs_manager_get_int(prefs_manager, "source-view", "draw-spaces", 0),
		"highlight-current-line", prefs_manager_get_bool(prefs_manager, "source-view", "highlight-current-line", TRUE),
		"indent-on-tab", prefs_manager_get_bool(prefs_manager, "source-view", "indent-on-tab", TRUE),
		"indent-width", prefs_manager_get_int(prefs_manager, "source-view", "indent-width", 4),
		"insert-spaces-instead-of-tabs", prefs_manager_get_bool(prefs_manager, "source-view", "insert-spaces-instead-of-tabs", FALSE),
		"right-margin-position", prefs_manager_get_int(prefs_manager, "source-view", "right-margin-position", 80),
		"show-line-marks", prefs_manager_get_bool(prefs_manager, "source-view", "show-line-marks", FALSE),
		"show-line-numbers", prefs_manager_get_bool(prefs_manager, "source-view", "show-line-numbers", TRUE),
		"show-right-margin", prefs_manager_get_bool(prefs_manager, "source-view", "show-right-margin", FALSE),
		"smart-home-end", prefs_manager_get_int(prefs_manager, "source-view", "smart-home-end", 0),
		"tab-width", prefs_manager_get_int(prefs_manager, "source-view", "tab-width", 4), NULL);
	
	gchar *font_desc_string = prefs_manager_get_string(prefs_manager, "source-view", "font", "mono");
	g_assert(font_desc_string != NULL);
	
	font_desc = pango_font_description_from_string (font_desc_string);
	gtk_widget_modify_font (GTK_WIDGET(view), font_desc);
	pango_font_description_free (font_desc);
	
	g_free(font_desc_string);
	
	return view;
	*/
	
	return NULL;
}
#endif /* ENABLE_SOURCE_VIEW */
